#include "musicplayer.h"
#include "ui_musicplayer.h"

#include <QMouseEvent>
#include <QGraphicsDropShadowEffect>
#include <QJsonObject>
#include <QJsonArray>
#include <QFileDialog>
#include <QMessageBox>
#include <QSqlQuery>
#include <QSystemTrayIcon>
#include <QMenu>


MusicPlayer::MusicPlayer(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MusicPlayer)
{
    ui->setupUi(this);

    //初始化页面
    initUi();

    //初始化数据库
    initSqlite();

    //初始化musicList
    initMusicList();

    //初始化媒体播放功能
    initPlayer();

    //连接所需信号槽
    connectSignalAndSlots();

}

MusicPlayer::~MusicPlayer()
{
    delete ui;
}

void MusicPlayer::initUi()
{
    this->setWindowFlag(Qt::FramelessWindowHint);

    //设置窗口背景透明
    this->setAttribute(Qt::WA_TranslucentBackground);
    //任务栏图标
    this->setWindowIcon(QIcon(":/images/tubiao.png"));

    //暂时屏蔽最大化窗口, 缩放比例不协调
    ui->max->setEnabled(false);

    //设置系统托盘
    QSystemTrayIcon *trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/images/tubiao.png"));
    trayIcon->show();
    //托盘添加菜单
    QMenu *trayMenu = new QMenu();
    trayMenu->addAction("显示", this, &MusicPlayer::show);
    trayMenu->addAction("退出", this, &MusicPlayer::onMusicPlayerQuit);
    trayIcon->setContextMenu(trayMenu);

    //窗口设置阴影效果
    QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setOffset(0,0);
    shadowEffect->setColor("#000000");
    shadowEffect->setBlurRadius(10);        //太大会造成歌词动画卡顿
    this->setGraphicsEffect(shadowEffect);

    //设置btForm的图标的文本
    ui->Rec->setIconAndText(":/images/rec.png", "推荐", 0);
    ui->radio->setIconAndText(":/images/radio.png", "电台", 1);
    ui->music->setIconAndText(":/images/music.png", "音乐馆", 2);
    ui->like->setIconAndText(":/images/like.png", "我的喜欢", 3);
    ui->local->setIconAndText(":/images/local.png", "本地音乐", 4);
    ui->recent->setIconAndText(":/images/recent.png", "最近播放", 5);

    //默认显示推荐页面
    ui->Rec->showStyle();
    ui->stackedWidget->setCurrentIndex(0);

    //初始化推荐页面
    srand(time(0));
    ui->recMusicBox->initRecBoxUi(randomPiction(), 1);
    ui->supplyMusicBox->initRecBoxUi(randomPiction(), 2);

    //初始化CommonPage页面
    ui->likePage->setMusicListType(PageType::LIKE_PAGE);
    ui->likePage->setCommonPageUi(":/images/ilikebg.png", "我喜欢");
    ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
    ui->localPage->setCommonPageUi(":/images/localbg.png", "本地音乐");
    ui->recentPage->setMusicListType(PageType::HISTORY_PAGE);
    ui->recentPage->setCommonPageUi(":/images/recentbg.png", "最近播放");

    //初始化播放控制区按钮图标
    ui->play->setIcon(QIcon(":/images/play_2.png"));
    ui->playMode->setIcon(QIcon(":/images/list_play.png"));
    ui->playMode->setToolTip("列表循环");

    //设置默认播放页面
    currentPage = ui->localPage;

    //调节音量弹窗初始化
    volumeTool = new VolumeTool();

    //歌词窗口初始化
    lrcPage = new LrcPage(this);
    lrcPage->setGeometry(10, 10, lrcPage->width(), lrcPage->height());
    lrcPage->hide();

    //初始化歌词上升动画
    lrcPageAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
    lrcPageAnimation->setDuration(500);
    lrcPageAnimation->setStartValue(QRect(10, 10+lrcPage->height(), lrcPage->width(), lrcPage->height()));
    lrcPageAnimation->setEndValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));
}

void MusicPlayer::initPlayer()
{
    //初始化媒体播放对象
    player = new QMediaPlayer(this);
    playlist = new QMediaPlaylist(this);

    //设置默认播放模式
    playlist->setPlaybackMode(QMediaPlaylist::Loop);

    //设置播放列表
    player->setPlaylist(playlist);

    //设置默认音量(20%)
    player->setVolume(20);
}

void MusicPlayer::initSqlite()
{
    //数据库驱动加载
    sqlite = QSqlDatabase::addDatabase("QSQLITE");

    //设置数据库名称
    sqlite.setDatabaseName("MusicPlayer.db");

    //打开
    if(!sqlite.open())
    {
        QMessageBox::critical(this, "MusicPlayer", "数据库打开失败!");
        return;
    }

    qDebug() << "数据库创建成功";

    //创建表
    QString sql = "CREATE TABLE IF NOT EXISTS MusicInfo (\
                  id INTEGER PRIMARY KEY AUTOINCREMENT,\
                  musicId varchar(50) UNIQUE,\
                  musicName varchar(50),\
                  musicSinger varchar(50),\
                  musicAlbum varchar(50),\
                  musicUrl varchar(256),\
                  musicTime BIGINT,\
                  isLike INTEGER,\
                  isHistory INTEGER)";

    //QString sql ="DROP TABLE MusicInfo";
    QSqlQuery query(sql);

    if(!query.exec())
    {
        QMessageBox::critical(this, "MusicPlayer", "初始化失败!");
        return;
    }

    qDebug() << "音乐数据表创建成功";

}

void MusicPlayer::initMusicList()
{
    musicList.readFromDB();

    ui->likePage->reFresh(musicList);

    ui->localPage->reFresh(musicList);

    ui->recentPage->reFresh(musicList);
}

void MusicPlayer::connectSignalAndSlots()
{
    //关联BtForm的信号和处理信号的槽函数
    connect(ui->Rec, &BtForm::btClick, this, &MusicPlayer::onBtFormClick);
    connect(ui->radio, &BtForm::btClick, this, &MusicPlayer::onBtFormClick);
    connect(ui->music, &BtForm::btClick, this, &MusicPlayer::onBtFormClick);
    connect(ui->like, &BtForm::btClick, this, &MusicPlayer::onBtFormClick);
    connect(ui->local, &BtForm::btClick, this, &MusicPlayer::onBtFormClick);
    connect(ui->recent, &BtForm::btClick, this, &MusicPlayer::onBtFormClick);

    //音乐收藏和取消收藏的处理
    connect(ui->likePage, &CommonPage::updateLikeMusic, this, &MusicPlayer::updateLikeMusicAndPage);
    connect(ui->localPage, &CommonPage::updateLikeMusic, this, &MusicPlayer::updateLikeMusicAndPage);
    connect(ui->recentPage, &CommonPage::updateLikeMusic, this, &MusicPlayer::updateLikeMusicAndPage);

    //播放控制区信号和槽函数关联
    connect(ui->play, &QPushButton::clicked, this, &MusicPlayer::onPlayMusicClicked);
    connect(ui->playUp, &QPushButton::clicked, this, &MusicPlayer::onPlayUpClicked);
    connect(ui->playDown, &QPushButton::clicked, this, &MusicPlayer::onPlayDownClicked);
    connect(ui->playMode, &QPushButton::clicked, this, &MusicPlayer::onPlayBackModeClicked);

    //播放所有按钮处理
    connect(ui->likePage, &CommonPage::playAll, this, &MusicPlayer::onPlayAll);
    connect(ui->localPage, &CommonPage::playAll, this, &MusicPlayer::onPlayAll);
    connect(ui->recentPage, &CommonPage::playAll, this, &MusicPlayer::onPlayAll);

    //likePage,localPage,recentPage页面歌曲被双击之后,播放相应音乐
    connect(ui->likePage, &CommonPage::playMusicByIndex, this, &MusicPlayer::playMusicByIndex);
    connect(ui->localPage, &CommonPage::playMusicByIndex, this, &MusicPlayer::playMusicByIndex);
    connect(ui->recentPage, &CommonPage::playMusicByIndex, this, &MusicPlayer::playMusicByIndex);

    //获取当前播放音乐的index
    connect(playlist, &QMediaPlaylist::currentIndexChanged, this, &MusicPlayer::onCurrentIndexChanged);

    //静音处理
    connect(volumeTool, &VolumeTool::setMusicMuted, this, &MusicPlayer::onSetMusicMuted);

    //设置音量大小
    connect(volumeTool, &VolumeTool::setPlayerVolume, this, &MusicPlayer::onSetPlayerVolume);

    //当播放音乐总时长改变durationChanged信号处理
    connect(player, &QMediaPlayer::durationChanged, this, &MusicPlayer::onDurationChanged);

    //当播放音乐播放进度改变positionChanged信号处理
    connect(player, &QMediaPlayer::positionChanged, this, &MusicPlayer::onPositionChanged);

    //关联进度条改变musicSliderChanged信号,同步播放进度
    connect(ui->progressBar, &MusicSlider::musicSliderChanged, this, &MusicPlayer::onMusicSliderChanged);

    //可用播放源改变后,更新播放控制区信息
    connect(player, &QMediaPlayer::metaDataAvailableChanged, this, &MusicPlayer::onMetaDataAvailableChanged);
}

void MusicPlayer::mouseMoveEvent(QMouseEvent *event)
{
    //保持鼠标与窗口左上角相对位置不变
    if(Qt::LeftButton == event->buttons())
    {
        move(event->globalPos() - dragPosition);
        return;
    }

    //我们不关心的鼠标事件交给QWidget默认处理
    QWidget::mouseMoveEvent(event);
}

void MusicPlayer::mousePressEvent(QMouseEvent *event)
{
    //如果左键被按下，记录当前鼠标相对窗口左上角的位置
    if(Qt::LeftButton == event->button())
    {
        dragPosition = event->globalPos() - geometry().topLeft();
        return;
    }

    //我们不关心的鼠标事件交给QWidget默认处理
    QWidget::mouseMoveEvent(event);
}

void MusicPlayer::on_quit_clicked()
{
    this->hide();
}

void MusicPlayer::onBtFormClick(int pageId)
{
    //清除所有btForm的颜色
    //获取界面中的所有btForm
    QList<BtForm*> allBtForm =  this->findChildren<BtForm*>();
    for(auto e : allBtForm)
    {
        if(e->getPageId() != pageId)
            e->clearBackGround();
    }

    ui->stackedWidget->setCurrentIndex(pageId);
}

void MusicPlayer::playAllMusicOfCommonPage(CommonPage *page, int index)
{
    //记录当前播放页面
    currentPage = page;

    //将相应音乐添加到当前页面中
    page->addMusicToPlaylist(musicList, playlist);

    //设置当前播放音乐索引
    playlist->setCurrentIndex(index);

    player->play();

    ui->play->setIcon(QIcon(":/images/play_on.png"));
}

void MusicPlayer::playMusicByIndex(CommonPage *page, int index)
{
    playAllMusicOfCommonPage(page, index);
}

void MusicPlayer::onCurrentIndexChanged(int index)
{
    this->index = index;

    //获取当前播放音乐的Id
    QString musicId = currentPage->getMusicIdByIndex(index);

    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        //设置历史播放属性
        it->setIsHistory(true);
    }

    ui->recentPage->reFresh(musicList);
}

void MusicPlayer::onSetMusicMuted(bool isMuted)
{
    //设置是否静音
    player->setMuted(isMuted);
}

void MusicPlayer::onSetPlayerVolume(int volume)
{
    player->setVolume(volume);
}

void MusicPlayer::onDurationChanged(qint64 duration)
{
    //duration(ms)为歌曲总时长
    //分: duration/1000/60
    //秒: duration/1000%60
    totalTime = duration;
    ui->totalTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10, QChar('0'))
                           .arg(duration/1000%60, 2, 10, QChar('0')));
}

void MusicPlayer::onPositionChanged(qint64 position)
{
    //position(ms)为歌曲播放进度
    //分: duration/1000/60
    //秒: duration/1000%60

    //同步进度条
    ui->progressBar->setStep(position/(float)totalTime);

    ui->currentTime->setText(QString("%1:%2").arg(position/1000/60, 2, 10, QChar('0'))
                             .arg(position/1000%60, 2, 10, QChar('0')));

    //同步歌词显示
    lrcPage->showLrcWordLine(position);
}

void MusicPlayer::onMusicSliderChanged(float ratio)
{
    qint64 position = totalTime*ratio;

    //同步歌曲进度
    player->setPosition(position);
}

void MusicPlayer::onMetaDataAvailableChanged(bool available)
{
    //获取当前播放音乐的Id
    QString musicId = currentPage->getMusicIdByIndex(index);

    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        //界面显示歌曲信息
        ui->musicName->setText(it->getMusicName());
        ui->musicSinger->setText(it->getMusicSinger());

        QVariant coverImage = player->metaData("ThumbnailImage");
        if(coverImage.isValid())
        {
            QImage image = coverImage.value<QImage>();
            ui->musicCover->setPixmap(QPixmap::fromImage(image));
        }
        else
        {
            qDebug()<<"此歌曲无封面图";
            //可以设置默认图片
            ui->musicCover->setPixmap(QPixmap(":/images/rec/025.png"));
        }
        //图片自动填充满空间
        ui->musicCover->setScaledContents(true);
    }

    //解析歌曲LRC歌词
    if(it != musicList.end())
    {
        //获取歌曲LRC文件路径
        QString lrcPath = it->getMusicLrcPath();

        //解析LRC文件
        lrcPage->parseLrcFile(lrcPath);
    }
}

QJsonArray MusicPlayer::randomPiction()
{
    QVector<QString> imagesFileName;
    imagesFileName<<"001.png"<<"003.png"<<"004.png"<<"005.png"<<"006.png"<<"007.png"
                  <<"008.png"<<"009.png"<<"010.png"<<"011.png"<<"012.png"<<"013.png"
                  <<"014.png"<<"015.png"<<"016.png"<<"017.png"<<"018.png"<<"019.png"
                  <<"020.png"<<"021.png"<<"022.png"<<"023.png"<<"024.png"<<"025.png"
                  <<"026.png"<<"027.png"<<"028.png"<<"029.png"<<"030.png"<<"031.png"
                  <<"032.png"<<"033.png"<<"034.png"<<"035.png"<<"036.png"<<"037.png"
                  <<"038.png"<<"039.png"<<"040.png";

    //随机图片名
    std::random_shuffle(imagesFileName.begin(), imagesFileName.end());

    QJsonArray objArray;
    for(int i =0; i < imagesFileName.size(); ++i)
    {
        QJsonObject json;
        json.insert("path", ":/images/rec/"+imagesFileName[i]);
        json.insert("text", QString("推荐-%1").arg(i, 3, 10, QChar('0')));

        objArray.append(json);
    }

    return objArray;
}

void MusicPlayer::onMusicPlayerQuit()
{
    //将musicList插入数据库中
    musicList.writeToDB();

    //断开与QSqlite的链接
    sqlite.close();

    //关闭窗口
    close();
}

void MusicPlayer::on_volum_clicked()
{
    //获取ui->volume的leftTop()相对于屏幕的全局坐标
    QPoint point = ui->volum->mapToGlobal(QPoint(0,0));

    //通过point得到volumeTool(音量调节框)在volume(音量键)上方的的合适位置
    int x = point.x() - volumeTool->width()/2 + ui->volum->width()/2;
    QPoint boxPoint = QPoint(x, point.y() - volumeTool->height() + 30);

    volumeTool->move(boxPoint);

    volumeTool->show();
}

void MusicPlayer::on_addLocal_clicked()
{
    //添加音乐弹窗
    QFileDialog fileDialog(this);

    //获取项目路径
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString projectPath = dir.path() + "/MusicPlayer/musics";

    //设置路径
    fileDialog.setDirectory(projectPath);

    //设置一次打开多个文件
    fileDialog.setFileMode(QFileDialog::ExistingFiles);

    //通过文件mime类型来过滤
    QStringList mimeTypeFilters;
    mimeTypeFilters<<"application/octet-stream";
    fileDialog.setMimeTypeFilters(mimeTypeFilters);

    if(fileDialog.exec() == QDialog::Accepted)
    {
        //显示本地音乐界面
        QMouseEvent *event = NULL;
        ui->local->mousePressEvent(event);

        QList<QUrl> fileUrls = fileDialog.selectedUrls();

        //将所有音乐添加到音乐列表中
        musicList.addMusicsByUrl(fileUrls);

        //刷新音乐列表
        ui->localPage->reFresh(musicList);

        //添加到播放列表
        ui->localPage->addMusicToPlaylist(musicList, playlist);
    }
}

void MusicPlayer::updateLikeMusicAndPage(bool isLike, const QString &musicId)
{
    //改变收藏状态
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        it->setIsLike(isLike);
    }

    //更新页面
    ui->likePage->reFresh(musicList);
    ui->localPage->reFresh(musicList);
    ui->recentPage->reFresh(musicList);
}

void MusicPlayer::onPlayMusicClicked()
{
    if(QMediaPlayer::PlayingState == player->state())
    {
        //当前为播放状态,点击后变为暂停
        player->pause();
        ui->play->setIcon(QIcon(":/images/play3.png"));
    }
    else if(QMediaPlayer::PausedState == player->state())
    {
        //当前为暂停状态,点击后变为播放
        player->play();
        ui->play->setIcon(QIcon(":/images/play_on.png"));
    }
    else if(QMediaPlayer::StoppedState == player->state())
    {
        //当前为停止状态,点击后变为播放
        player->play();
        ui->play->setIcon(QIcon(":/images/play_on.png"));
    }
    else
    {
        //发生错误
        qDebug()<<player->errorString();
    }
}

void MusicPlayer::onPlayUpClicked()
{
    playlist->previous();
}

void MusicPlayer::onPlayDownClicked()
{
    playlist->next();
}

void MusicPlayer::onPlayBackModeClicked()
{
    //列表循环->随机播放->单曲循环
    if(playlist->playbackMode() == QMediaPlaylist::Loop)
    {
        playlist->setPlaybackMode(QMediaPlaylist::Random);
        ui->playMode->setIcon(QIcon(":/images/shuffle_2.png"));
        ui->playMode->setToolTip("随机播放");
    }
    else if(playlist->playbackMode() == QMediaPlaylist::Random)
    {
        playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
        ui->playMode->setIcon(QIcon(":/images/single_play.png"));
        ui->playMode->setToolTip("单曲循环");
    }
    else if(playlist->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
        playlist->setPlaybackMode(QMediaPlaylist::Loop);
        ui->playMode->setIcon(QIcon(":/images/list_play.png"));
        ui->playMode->setToolTip("列表循环");
    }
    else
    {
        qDebug()<<"暂不支持";
    }
}

void MusicPlayer::onPlayAll(PageType pageType)
{
    //通过pageType找到信号发出页面
    CommonPage *page = ui->localPage;
    switch (pageType)
    {
        case PageType::LIKE_PAGE:
        page = ui->likePage;
        break;
        case PageType::LOCAL_PAGE:
        page = ui->localPage;
        break;
        case PageType::HISTORY_PAGE:
        page = ui->recentPage;
        break;
        default:
        qDebug() << "尚未支持";
    }

    //播放页面全部歌曲,默认第0首开始
    playAllMusicOfCommonPage(page, 0);
}

void MusicPlayer::on_lrcWord_clicked()
{
    lrcPage->show();
    lrcPageAnimation->start();
}

void MusicPlayer::on_min_clicked()
{
    this->showMinimized();
}
